﻿using System;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Printing;
using System.Drawing.Drawing2D;

namespace RmsBarcode
{
    public partial class RmsBarcode : UserControl
    {
        public RmsBarcode()
        {
            InitializeComponent();
        }


        public enum AlignType
        {
            Left, Center, Right
        }

        public enum CodeWeight
        {
            Small = 1, Medium, Large
        }

        public enum CodeType
        {
            Code39 = 1, Code39_Extended, Code93, Code128, Code128_A, Code128_B, Code128_C
        }

        private AlignType align = AlignType.Left;
        private AlignType barCodeAlign = AlignType.Left;
        private String code = "1234567890";
        private int leftMargin = 15;
        private int topMargin = 15;
        private int barCodeheight = 35;
        private bool showHeader=true;
        private bool showFooter = true;
        private bool showPrice = true;
        private float reduceCoefficient = 1f;
        private String headerText = "BarCode Demo";
        private String priceText = "￥0.00";
        private CodeWeight barCodeWeight = CodeWeight.Small;
        private CodeType barCodeType = CodeType.Code39;
        private Font headerFont = new Font("Courier", 12);
        private Font priceFont = new Font("Courier", 12);
        private Font footerFont = new Font("Courier", 8);
        private int printTimes = 1;
        private String[] barCodeList;

        private int currPrintCount = 0;
        private Boolean isPrintList = false;
        private int currBarcodePosition = 0;

        public AlignType VertAlign
        {
            get { return align; }
            set { align = value; panel1.Invalidate(); }
        }

        public AlignType BarCodeAlign
        {
            get { return barCodeAlign; }
            set { barCodeAlign = value; panel1.Invalidate(); }
        }

        public String BarCode
        {
            get { return code; }
            set { code = value; panel1.Invalidate(); }
        }

        public String[] BarCodeList
        {
            get { return barCodeList; }
            set { barCodeList = value; panel1.Invalidate(); }
        }

        public int PrintTimes
        {
            get { return printTimes; }
            set { printTimes = value; panel1.Invalidate(); }
        }

        public int BarCodeHeight
        {
            get { return barCodeheight; }
            set { barCodeheight = value; panel1.Invalidate(); }
        }

        public int LeftMargin
        {
            get { return leftMargin; }
            set { leftMargin = value; panel1.Invalidate(); }
        }

        public int TopMargin
        {
            get { return topMargin; }
            set { topMargin = value; panel1.Invalidate(); }
        }

        public bool ShowHeader
        {
            get { return showHeader; }
            set { showHeader = value; panel1.Invalidate(); }
        }

        public bool ShowPrice
        {
            get { return showPrice; }
            set { showPrice = value; panel1.Invalidate(); }
        }

        public bool ShowFooter
        {
            get { return showFooter; }
            set { showFooter = value; panel1.Invalidate(); }
        }

        public float ReduceCoefficient
        {
            get { return reduceCoefficient; }
            set { reduceCoefficient = value; panel1.Invalidate(); }
        }

        public String HeaderText
        {
            get { return headerText; }
            set { headerText = value; panel1.Invalidate(); }
        }

        public String PriceText
        {
            get { return priceText; }
            set { priceText = value; panel1.Invalidate(); }
        }

        public CodeWeight BarCodeWeight
        {
            get { return barCodeWeight; }
            set { barCodeWeight = value; panel1.Invalidate(); }
        }

        public CodeType BarCodeType
        {
            get { return barCodeType; }
            set { barCodeType = value; panel1.Invalidate(); }
        }

        public Font HeaderFont
        {
            get { return headerFont; }
            set { headerFont = value; panel1.Invalidate(); }
        }

        public Font PriceFont
        {
            get { return priceFont; }
            set { priceFont = value; panel1.Invalidate(); }
        }

        public Font FooterFont
        {
            get { return footerFont; }
            set { footerFont = value; panel1.Invalidate(); }
        }

        #region Old39Code

        //String alphabet39 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*";

        //String[] coded39Char = 
        //{
        //    /* 0 */ "000110100", 
        //    /* 1 */ "100100001", 
        //    /* 2 */ "001100001", 
        //    /* 3 */ "101100000",
        //    /* 4 */ "000110001", 
        //    /* 5 */ "100110000", 
        //    /* 6 */ "001110000", 
        //    /* 7 */ "000100101",
        //    /* 8 */ "100100100", 
        //    /* 9 */ "001100100", 
        //    /* A */ "100001001", 
        //    /* B */ "001001001",
        //    /* C */ "101001000", 
        //    /* D */ "000011001", 
        //    /* E */ "100011000", 
        //    /* F */ "001011000",
        //    /* G */ "000001101", 
        //    /* H */ "100001100", 
        //    /* I */ "001001100", 
        //    /* J */ "000011100",
        //    /* K */ "100000011", 
        //    /* L */ "001000011", 
        //    /* M */ "101000010", 
        //    /* N */ "000010011",
        //    /* O */ "100010010", 
        //    /* P */ "001010010", 
        //    /* Q */ "000000111", 
        //    /* R */ "100000110",
        //    /* S */ "001000110", 
        //    /* T */ "000010110", 
        //    /* U */ "110000001", 
        //    /* V */ "011000001",
        //    /* W */ "111000000", 
        //    /* X */ "010010001", 
        //    /* Y */ "110010000", 
        //    /* Z */ "011010000",
        //    /* - */ "010000101", 
        //    /* . */ "110000100", 
        //    /*' '*/ "011000100",
        //    /* $ */ "010101000",
        //    /* / */ "010100010", 
        //    /* + */ "010001010", 
        //    /* % */ "000101010", 
        //    /* * */ "010010100" 
        //};

        //private void panel1_Paint(object sender, PaintEventArgs e)
        //{
        //    String intercharacterGap = "0";
        //    String str = '*' + code + '*';
        //    int strLength = str.Length;

        //    for (int i = 0; i < code.Length; i++)
        //    {
        //        if (alphabet39.IndexOf(code[i]) == -1 || code[i] == '*')
        //        {
        //            e.Graphics.DrawString("INVALID BAR CODE TEXT", Font, Brushes.Red, 10, 10);
        //            return;
        //        }
        //    }

        //    String encodedString = "";

        //    for (int i = 0; i < strLength; i++)
        //    {
        //        if (i > 0)
        //            encodedString += intercharacterGap;

        //        encodedString += coded39Char[alphabet39.IndexOf(str[i])];
        //    }

        //    int encodedStringLength = encodedString.Length;
        //    float  widthOfBarCodeString = 0f;
        //    double wideToNarrowRatio = 3;


        //    if (align != AlignType.Left)
        //    {
        //        for (int i = 0; i < encodedStringLength; i++)
        //        {
        //            if (encodedString[i] == '1')
        //                widthOfBarCodeString += (float)(wideToNarrowRatio * (float)weight) * reduceCoefficient;
        //            else
        //                widthOfBarCodeString += (float)weight * reduceCoefficient;
        //        }
        //    }

        //    //for (int iTimes = 0; iTimes < 3; iTimes++)
        //    //{
        //        int x = 0;
        //        int wid = 0;
        //        int yTop = 0 * 110;
        //        SizeF hSize = e.Graphics.MeasureString(headerText, headerFont);
        //        SizeF fSize = e.Graphics.MeasureString(code, footerFont);
        //        SizeF pSize = e.Graphics.MeasureString(priceText, priceFont);

        //        int headerX = 0;
        //        int footerX = 0;
        //        int priceX = 0;

        //        if (align == AlignType.Left)
        //        {
        //            x = leftMargin;
        //            headerX = leftMargin;
        //            footerX = leftMargin;
        //            priceX = leftMargin;

        //        }
        //        else if (align == AlignType.Center)
        //        {
        //            x = (Width - (int)widthOfBarCodeString) / 2;
        //            headerX = (Width - (int)hSize.Width) / 2;
        //            footerX = (Width - (int)fSize.Width) / 2;
        //            priceX = (Width - (int)pSize.Width) / 2;
        //        }
        //        else
        //        {
        //            x = Width - (int)widthOfBarCodeString - leftMargin;
        //            headerX = Width - (int)hSize.Width - leftMargin;
        //            footerX = Width - (int)fSize.Width - leftMargin;
        //            priceX = Width - (int)pSize.Width - leftMargin;
        //        }

        //        if (!ShowPrice)
        //        {
        //            yTop += (int)(pSize.Height / 2) + topMargin;
        //        }
        //        else
        //        {
        //            yTop += topMargin;
        //        }


        //        if (showHeader)
        //        {
        //            e.Graphics.DrawString(headerText, headerFont, Brushes.Black, headerX, yTop);
        //            yTop += (int)hSize.Height;
        //        }
        //        else
        //        {
        //            yTop += (int)(hSize.Height / 2);
        //        }

        //        if (showPrice)
        //        {
        //            e.Graphics.DrawString(priceText, priceFont, Brushes.Black, headerX, yTop);
        //            yTop += (int)pSize.Height;
        //        }

        //        float fx = (float)x;


        //        for (int i = 0; i < encodedStringLength; i++)
        //        {
        //            if (encodedString[i] == '1')
        //                wid = (int)(wideToNarrowRatio * (int)weight);
        //            else
        //                wid = (int)weight;
        //            float fwid = (float)wid * reduceCoefficient;

        //            e.Graphics.FillRectangle(i % 2 == 0 ? Brushes.Black : Brushes.White, fx, yTop, fwid, 35);
        //            fx += fwid;
        //        }

        //        yTop += height;

        //        if (showFooter)
        //            e.Graphics.DrawString(code, footerFont, Brushes.Black, footerX, yTop);
        //    //}
        //}

        #endregion

        private void panel1_Paint(object sender, PaintEventArgs e)
        {

            ICode iCode = null;

            switch (barCodeType)
            {
                case CodeType.Code39: 
                    iCode = new Code39(code);
                    break;
                case CodeType.Code39_Extended :
                    iCode = new Code39(code, true);
                    break;
                case CodeType.Code93 :
                    iCode =new Code93(code);
                    break;
                case CodeType.Code128 :
                    iCode = new Code128(code);
                    break;
                case CodeType.Code128_A :
                    iCode = new Code128(code, Code128.TYPES.A);
                    break;
                case CodeType.Code128_B:
                    iCode = new Code128(code, Code128.TYPES.B);
                    break;
                case CodeType.Code128_C:
                    iCode = new Code128(code, Code128.TYPES.C);
                    break;

            }

            String encodedString = iCode.Encoded_Value;

            int encodedStringLength = encodedString.Length;
            float widthOfBarCodeString = 0f;

            widthOfBarCodeString = (float)barCodeWeight * reduceCoefficient * encodedString.Length;

            int x = 0;
            int yTop = 0 ;
            SizeF hSize = e.Graphics.MeasureString(headerText, headerFont);
            SizeF fSize = e.Graphics.MeasureString(code, footerFont);
            SizeF pSize = e.Graphics.MeasureString(priceText, priceFont);

            int headerX = 0;
            int footerX = 0;
            int priceX = 0;

            if (align == AlignType.Left)
            {
                headerX = leftMargin;
                footerX = leftMargin;
                priceX = leftMargin;

            }
            else if (align == AlignType.Center)
            {
                headerX = (Width - (int)hSize.Width) / 2;
                footerX = (Width - (int)fSize.Width) / 2;
                priceX = (Width - (int)pSize.Width) / 2;
            }
            else
            {
                headerX = Width - (int)hSize.Width - leftMargin;
                footerX = Width - (int)fSize.Width - leftMargin;
                priceX = Width - (int)pSize.Width - leftMargin;
            }

            if (barCodeAlign == AlignType.Left)
            {
                x = leftMargin;
            }
            else if (barCodeAlign == AlignType.Center)
            {
                x = (Width - (int)widthOfBarCodeString) / 2;
            }
            else
            {
                x = Width - (int)widthOfBarCodeString - leftMargin;
            }
            
            if (!ShowPrice)
            {
                yTop += (int)(pSize.Height / 2) + topMargin;
            }
            else
            {
                yTop += topMargin;
            }


            if (showHeader)
            {
                e.Graphics.DrawString(headerText, headerFont, Brushes.Black, headerX, yTop);
                yTop += (int)hSize.Height;
            }
            else
            {
                yTop += (int)(hSize.Height / 2);
            }

            if (showPrice)
            {
                e.Graphics.DrawString(priceText, priceFont, Brushes.Black, priceX, yTop);
                yTop += (int)pSize.Height;
            }

            float fx = (float)x;

            Pen pen = new Pen(ForeColor, (float)barCodeWeight * reduceCoefficient);

            pen.Alignment = PenAlignment.Right;
            int pos = 0;
            while (pos < encodedString.Length)
            {
                if (encodedString[pos] == '1')
                    e.Graphics.DrawLine(pen, new PointF((float)pos * (float)barCodeWeight * reduceCoefficient + fx, (float)yTop), new PointF((float)pos * (float)barCodeWeight * reduceCoefficient + fx, (float)yTop + (float)barCodeheight));
                pos++;
            }

            yTop += barCodeheight;

            if (showFooter)
                e.Graphics.DrawString(code, footerFont, Brushes.Black, footerX, yTop);
        }

        public void SaveImage(String file)
        {
            Bitmap bmp = new Bitmap(Width, Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

            Graphics g = Graphics.FromImage(bmp);
            g.FillRectangle(Brushes.White, 0, 0, Width, Height);

            panel1_Paint(null, new PaintEventArgs(g, this.ClientRectangle));

            bmp.Save(file);
        }

        private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            e.HasMorePages = true;
            if (isPrintList)
            {
                if (currBarcodePosition < barCodeList.Length)
                {
                    code = barCodeList[currBarcodePosition];
                    panel1_Paint(sender, new PaintEventArgs(e.Graphics, this.ClientRectangle));
                    currBarcodePosition++;
                }
                if (currBarcodePosition == barCodeList.Length)
                {
                    currBarcodePosition = 0;
                    currPrintCount++;
                    if (currPrintCount >= printTimes)
                    {
                        e.HasMorePages = false;
                        currPrintCount = 0;
                    }
                }
            }
            else
            {
                panel1_Paint(sender, new PaintEventArgs(e.Graphics, this.ClientRectangle));
                currPrintCount++;
                if (currPrintCount >= printTimes)
                {
                    e.HasMorePages = false;
                    currPrintCount = 0;
                }
            }
        }

        private void RmsBarcode_Resize(object sender, EventArgs e)
        {
            panel1.Invalidate();
        }

        public void Print(bool showDialog)
        {
            printDialogBarcode.Document = printDocumentBarcode;
            printDocumentBarcode.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
            //printDocumentBarcode.DefaultPageSettings.PaperSize.Kind = PaperKind.Custom;
            //printDocumentBarcode.DefaultPageSettings.PaperSize.Height = 110;
            //printDocumentBarcode.DefaultPageSettings.PaperSize.Width = 189;
            if (showDialog)
            {
                if (printDialogBarcode.ShowDialog() == DialogResult.OK)
                {
                    //for (int i = 0; i < printTimes; i++)
                        printDialogBarcode.Document.Print();
                }
            }
            else
            {
                //for (int i = 0; i < printTimes; i++)
                    printDialogBarcode.Document.Print();
            }
        }

        public void PrintList(bool showDialog)
        {
            if (barCodeList.Length > 0)
                isPrintList = true;
            printDialogBarcode.Document = printDocumentBarcode;
            printDocumentBarcode.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
            if (showDialog)
            {
                if (printDialogBarcode.ShowDialog() == DialogResult.OK)
                {
                    printDialogBarcode.Document.Print();
                }
            }
            else
            {
                printDialogBarcode.Document.Print();
            }
        }

        private void PrintBarcodeList()
        {
            foreach (String singleBarcode in barCodeList)
            {
                code = singleBarcode;
                printDialogBarcode.Document.Print();
            }
        }

        public void SaveImageList(String Folder)
        {
            if (Folder.Substring(Folder.Length - 1, 1) != "\\")
                Folder += "\\";
            foreach (String singleBarcode in barCodeList)
            {
                code = singleBarcode;
                SaveImage(Folder + singleBarcode + ".bmp");
            }
        }
    }
}
